<?php

namespace framework\libraries;

use InvalidArgumentException;

class Utils
{
    static  function randomString(string $type = 'alnum', int $len = 8): string
    {
        switch ($type) {
            case 'alnum':
            case 'nozero':
            case 'alpha':
                switch ($type) {
                    case 'alpha':
                        $pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                        break;

                    case 'alnum':
                        $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                        break;

                    case 'nozero':
                        $pool = '123456789';
                        break;
                }

                return self::_from_random($len, $pool);

            case 'numeric':
                $max  = 10 ** $len - 1;
                $rand = random_int(0, $max);

                return sprintf('%0' . $len . 'd', $rand);

            case 'md5':
                return md5(uniqid((string) mt_rand(), true));

            case 'sha1':
                return sha1(uniqid((string) mt_rand(), true));

            case 'crypto':
                if ($len % 2 !== 0) {
                    throw new InvalidArgumentException(
                        'You must set an even number to the second parameter when you use `crypto`.'
                    );
                }

                return bin2hex(random_bytes($len / 2));
        }

        // 'basic' type treated as default
        return (string) mt_rand();
    }

    static function _from_random(int $length, string $pool): string
    {
        if ($length <= 0) {
            throw new InvalidArgumentException(
                sprintf('A strictly positive length is expected, "%d" given.', $length)
            );
        }

        $poolSize = \strlen($pool);
        $bits     = (int) ceil(log($poolSize, 2.0));
        if ($bits <= 0 || $bits > 56) {
            throw new InvalidArgumentException(
                'The length of the alphabet must in the [2^1, 2^56] range.'
            );
        }

        $string = '';

        while ($length > 0) {
            $urandomLength = (int) ceil(2 * $length * $bits / 8.0);
            $data          = random_bytes($urandomLength);
            $unpackedData  = 0;
            $unpackedBits  = 0;

            for ($i = 0; $i < $urandomLength && $length > 0; $i++) {
                // Unpack 8 bits
                $unpackedData = ($unpackedData << 8) | \ord($data[$i]);
                $unpackedBits += 8;

                // While we have enough bits to select a character from the alphabet, keep
                // consuming the random data
                for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
                    $index = ($unpackedData & ((1 << $bits) - 1));
                    $unpackedData >>= $bits;
                    // Unfortunately, the alphabet size is not necessarily a power of two.
                    // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
                    // have around a 50% chance of missing as k gets larger
                    if ($index < $poolSize) {
                        $string .= $pool[$index];
                        $length--;
                    }
                }
            }
        }

        return $string;
    }


    /**
     * 获得两个字符串之间的字符串
     * @param $input
     * @param $start
     * @param $end
     * @return false|string
     */
    static function getBetweenString($input, $start, $end)
    {

        $substr = substr($input, strlen($start) + strpos($input, $start), (strlen($input) - strpos($input, $end)) * (-1));

        return $substr;
    }


    /**
     * 过滤数组
     * @param $inArray
     * @param $attributes
     * @param $prefix
     * @return array
     */
    static function filterArray($in, $fields, $tablePrefix = null)
    {
        $data = [];
        foreach ($fields as $key => $field) {
            if (is_numeric($key) && isset($in[$field])) {
                $data[$field] =  $in[$field];
            } elseif (isset($in[$key])) {
                if ($field == '@number') {
                    $data[$key] = floatval($in[$key]);
                } elseif ($field == '@bigint') {
                    $data[$key] = gmp_intval($in[$key]);
                } elseif ($field == '@string') {
                    $data[$key] = (string)$in[$key];
                } else {
                    $data[$key] = $in[$key];
                }
            }
        }
        return $data;
    }

    /**
     * 清除数据中不要的字段
     * @param array $arr
     * @param array $cleans
     * @return array
     */
    static function cleanArray(array $arr, array $cleans)
    {
        foreach ($cleans as $clean) {
            unset($arr[$clean]);
        }
        return $arr;
    }


    /**
     * 加密图形验证码
     * @param $username
     * @param $password
     * @param string $key
     * @return string
     */
    static function EncodeCaptcha($username, $password, $key = null)
    {
        if (!$key) {
            $key = $_ENV['CAPTCHA_SECRET_KEY'] ?? 'WeeSpeed@captcha';
        }
        return md5($password . $key . $username);
    }

    /**
     * 加密后台用户密码
     * @param $username
     * @param $password
     * @param string $key
     * @return string
     */
    static function EncodeAdminPassword($username, $password, $key = null)
    {
        if (!$key) {
            $key = $_ENV['ADMIN_SECRET_KEY'] ?? 'WeeSpeed@admin';
        }
        return md5($password . $key . md5($username));
    }
}
